package com.modificial.shiro.controller;

import com.modificial.shiro.system.vo.UserPassword;
import com.modificial.shiro.util.JsonResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.crypto.SecureRandomNumberGenerator;
import org.apache.shiro.crypto.hash.DefaultHashService;
import org.apache.shiro.crypto.hash.HashRequest;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.ByteSource;
import org.apache.shiro.util.SimpleByteSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

/**
 * @author modificial
 * @date 2018/8/5 0005
 * @company modificial_org
 * @description
 */
@Controller
@RequestMapping("/admin")
@Api(tags = "用户登录")
public class LoginController {
    private static Logger logger = LoggerFactory.getLogger(LoginController.class);

    @Autowired
    private SecurityManager securityManager;

    /**
     * 用户名密码登录
     *
     * @param userPassword
     * @return
     */
    @PostMapping("/login")
    @ApiOperation(value = "用户登录")
    @ResponseBody
    public JsonResult login(@RequestBody UserPassword userPassword, RedirectAttributes redirectAttributes) {
        Assert.notNull(userPassword, "用户名或密码不能为空");
        System.out.println(userPassword.isRememberMe());
        UsernamePasswordToken token = new UsernamePasswordToken(userPassword.getUserName(), userPassword.getPassword());
        Subject subject = SecurityUtils.getSubject();
        String username = userPassword.getUserName();
        if (userPassword.isRememberMe()) {
            token.setRememberMe(true);
        }
        try {
            //在调用了login方法后,SecurityManager会收到AuthenticationToken,并将其发送给已配置的Realm执行必须的认证检查
            //每个Realm都能在必要时对提交的AuthenticationTokens作出反应
            //所以这一步在调用login(token)方法时,它会走到MyRealm.doGetAuthenticationInfo()方法中,具体验证方式详见此方法
            logger.info("对用户[" + username + "]进行登录验证..验证开始");
            subject.login(token);
            logger.info("对用户[" + username + "]进行登录验证..验证通过");
        } catch (UnknownAccountException uae) {
            logger.info("对用户[" + username + "]进行登录验证..验证未通过,未知账户");
            redirectAttributes.addFlashAttribute("message", "未知账户");
        } catch (IncorrectCredentialsException ice) {
            logger.info("对用户[" + username + "]进行登录验证..验证未通过,错误的凭证");
            redirectAttributes.addFlashAttribute("message", "密码不正确");
        } catch (LockedAccountException lae) {
            logger.info("对用户[" + username + "]进行登录验证..验证未通过,账户已锁定");
            redirectAttributes.addFlashAttribute("message", "账户已锁定");
        } catch (ExcessiveAttemptsException eae) {
            logger.info("对用户[" + username + "]进行登录验证..验证未通过,错误次数过多");
            redirectAttributes.addFlashAttribute("message", "用户名或密码错误次数过多");
        } catch (AuthenticationException ae) {
            //通过处理Shiro的运行时AuthenticationException就可以控制用户登录失败或密码错误时的情景
            logger.info("对用户[" + username + "]进行登录验证..验证未通过,堆栈轨迹如下");
            ae.printStackTrace();
            redirectAttributes.addFlashAttribute("message", "用户名或密码不正确");
        }
        //验证是否登录成功
        if (subject.isAuthenticated()) {
            logger.info("用户[" + username + "]登录认证通过");
            Session session = subject.getSession(true);
            session.setAttribute("user", subject.getPrincipal());
            JsonResult jsonResult = new JsonResult(HttpStatus.OK.value(), "登录成功", 1);
            SecurityUtils.setSecurityManager(securityManager);
            return jsonResult;
        } else {
            token.clear();
            return new JsonResult(HttpStatus.OK.value(), "登录失败，请重新登录", 0);
        }
    }

    @GetMapping("/hello")
    public String hello() {
        return "test";
    }

    @GetMapping("/index")
    public String index() {
        return "index";
    }

    @GetMapping("/doLogin")
    public String doLogin() {
        return "login";
    }

    @GetMapping("/logout")
    @ResponseBody
    public String logout() {
        Subject subject = SecurityUtils.getSubject();
        subject.logout();
        return "退出登录成功";
    }

    /**
     * 被踢出后跳转的页面
     */
    @RequestMapping(value = "/kickOut", method = RequestMethod.GET)
    public String kickOut() {
        Subject subject = SecurityUtils.getSubject();
        subject.logout();
        return "kickOut";
    }

}
